﻿using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Configuration;
using System.Web.UI;

namespace BMap
{
    internal static class JavascriptRenderer
    {
        private static string GetClientId(string mapId)
        {
            return Regex.Replace(mapId, "[^a-z0-9A-Z]+", "_");
        }

        public static void FuncBegin(this HtmlTextWriter writer, string mapId)
        {
            writer.Write("<script>");
            writer.Write(Javascript.BmapPush);
        }

        public static void InitMap(this HtmlTextWriter writer, string mapId, double latitude, double longitude, int zoom)
        {
            var clientId = GetClientId(mapId);
            writer.Write("window.Map_{0}= new BMap.Map('{4}');window.Map_{0}.centerAndZoom(new BMap.Point({1}, {2}), {3});",
                clientId, latitude, longitude, zoom, mapId);
        }

        public static void FuncEnd(this HtmlTextWriter writer)
        {
            writer.Write("});</script>");
        }

        public static void RenderJsInclude(this HtmlTextWriter writer, string mapId)
        {
            var ver = WebConfigurationManager.AppSettings["BaiduMap.Version"];
            double version;
            if (!double.TryParse(ver, out version))
            {
                version = 1.5;
            }
            var ak = WebConfigurationManager.AppSettings["BaiduMap.AK"];
            var jsUrl = version > 1.4
                ? string.Format("http://api.map.baidu.com/getscript?v={0}&ak={1}&services=&t=20141117084945", version, ak)
                : string.Format("http://api.map.baidu.com/getscript?v={0}&t=20141117084945", version);

            if (HttpContext.Current.Items["BMap_JS"] == null)
            {
                writer.Write(@"<script>{0}</script>", Javascript.BMap);
                writer.Write(Javascript.IncludeJavascript, jsUrl);
                HttpContext.Current.Items["BMap_JS"] = new object();
            }
        }

        private static string RenderMarker(string mapId, int index, MapMarker marker)
        {
            if (marker == null)
            {
                return null;
            }
            var builder = new StringBuilder();
            var markerName = string.Format("{0}_marker{1}", mapId, index);
            builder.AppendFormat("var {0} = new BMap.Marker(", markerName);
            builder.AppendFormat("new BMap.Point({0}, {1})",marker.Latitude, marker.Longitude);
            if (!string.IsNullOrEmpty(marker.IconUrl))
            {
                builder.AppendFormat(",{{icon:new BMap.Icon(\"{0}\",new BMap.Size({1},{2}))}}", marker.IconUrl, marker.IconWidth, marker.IconHeight);
            }
            builder.Append(");");
            builder.AppendFormat("window.Map_{0}.addOverlay({1});", mapId, markerName);
            builder.AppendFormat("window.Map_{0}.markers.push({1});", mapId, markerName);
            if (marker.Draggable)
            {
                builder.AppendFormat("{0}.enableDragging();", markerName);
            }
            if (!string.IsNullOrEmpty(marker.Animation))
            {
                builder.AppendFormat("{0}.setAnimation({1});", markerName, marker.Animation);
            }
            if (!string.IsNullOrEmpty(marker.OnClientClick))
            {
                builder.AppendFormat("{0}.addEventListener(\"click\",function(){{if(typeof {1} ===\"function\"){{{1}({0});}}}});", markerName, marker.OnClientClick);
            }
            return builder.ToString();
        }

        public static void RenderMapMarker(this HtmlTextWriter writer, string mapId, IEnumerable<MapMarker> markers)
        {
            if (markers == null || !markers.Any())
            {
                return;
            }
            mapId = GetClientId(mapId);
            writer.Write("window.Map_{0}.markers=[];", mapId);
            var mapMarkers = markers as MapMarker[] ?? markers.ToArray();
            for (int i = 0; i < mapMarkers.Length; i++)
            {
                writer.Write(RenderMarker(mapId, i, mapMarkers[i]));
            }
        }

        private static string RenderOption(MapControlOption opt)
        {
            if (opt == null)
            {
                return null;
            }
            if (opt.X == 0 && opt.Y == 0 && string.IsNullOrEmpty(opt.Type) && opt.Anchor == MapAnchorEnum.None)
            {
                return null;
            }
            var builder = new StringBuilder();
            builder.Append("{");
            if (opt.X != 0 || opt.Y != 0)
            {
                builder.AppendFormat("offset:new BMap.Size({0}, {1}),", opt.X, opt.Y);
            }
            if (!string.IsNullOrEmpty(opt.Type))
            {
                builder.AppendFormat("type:{0},", opt.Type);
            }
            if (opt.Anchor != MapAnchorEnum.None)
            {
                builder.AppendFormat("anchor:{0},", opt.Anchor);
            }
            var str = builder.ToString().TrimEnd(',');
            return str + "}";
        }

        public static void RenderMapControl(this HtmlTextWriter writer, string mapId, IEnumerable<MapControl> ctrls)
        {
            if (ctrls == null || !ctrls.Any())
                return;
            mapId = GetClientId(mapId);
            foreach (var ctrl in ctrls)
            {
                writer.Write("window.Map_{0}.addControl(", mapId);
                writer.Write("new BMap.{0}(", ctrl.ControlType);
                writer.Write(RenderOption(ctrl.Option));
                writer.Write("));");
            }
        }
    }
}
